
#include <cstdio>
#include "member_BSerialPort.h"

using namespace BWE;

member_BSerialPort::member_BSerialPort(BSerialPort* serialPort)
{
	boss = serialPort;
	mode = IO_None;
	baudRate = BSerialPort::BaudNone;
	dataBits = BSerialPort::DataNone;
	direction = BSerialPort::DirectNone;
	flowControl = BSerialPort::FlowNone;
	parity = BSerialPort::ParityNone;
	stopBits = BSerialPort::StopNone;
#ifdef linux
	hcom = -1;
#endif
#ifdef _WIN32
	hcom = INVALID_HANDLE_VALUE;
#endif
}
member_BSerialPort::~member_BSerialPort()
{

}

void member_BSerialPort::freshComState()
{
#ifdef linux
	struct termios newtio, oldtio; 
	if  (tcgetattr(hcom, &oldtio) != 0)
	{  
		perror("SetupSerial 1");
		printf("tcgetattr( fd,&oldtio) -> %d\n",tcgetattr(hcom, &oldtio)); 
		return; 
	}
	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag |= CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;
	switch(dataBits)
	{ 
	case BSerialPort::Data5: 
		newtio.c_cflag |= CS5; 
		break; 
	case BSerialPort::Data6: 
		newtio.c_cflag |= CS6; 
		break; 
	case BSerialPort::Data7: 
		newtio.c_cflag |= CS7; 
		break; 
	case BSerialPort::Data8: 
		newtio.c_cflag |= CS8; 
		break; 
	} 
	switch(parity) 
	{
	case BSerialPort::ParityOdd:
		newtio.c_cflag |= PARENB; 
		newtio.c_cflag |= PARODD; 
		newtio.c_iflag |= (INPCK | ISTRIP); 
		break; 
	case BSerialPort::ParityEven:
		newtio.c_iflag |= (INPCK | ISTRIP); 
		newtio.c_cflag |= PARENB; 
		newtio.c_cflag &= ~PARODD; 
		break;
	case BSerialPort::ParityMark:
		break;
	case BSerialPort::ParitySpace:
		break;
	default:
		newtio.c_cflag &= ~PARENB; 
		break;
	} 
	switch(baudRate) 
     { 
	case BSerialPort::Baud1200:
		cfsetispeed(&newtio, B1200); 
		cfsetospeed(&newtio, B1200); 
		break; 
	case BSerialPort::Baud2400: 
		cfsetispeed(&newtio, B2400); 
		cfsetospeed(&newtio, B2400); 
		break; 
	case BSerialPort::Baud4800: 
		cfsetispeed(&newtio, B4800); 
		cfsetospeed(&newtio, B4800); 
		break; 
	case BSerialPort::Baud9600: 
		cfsetispeed(&newtio, B9600); 
		cfsetospeed(&newtio, B9600); 
		break; 
	case BSerialPort::Baud19200:
		cfsetispeed(&newtio, B19200); 
		cfsetospeed(&newtio, B19200); 
		break; 
	case BSerialPort::Baud38400:
		cfsetispeed(&newtio, B38400); 
		cfsetospeed(&newtio, B38400); 
		break; 
	default: 
		cfsetispeed(&newtio, B9600); 
		cfsetospeed(&newtio, B9600); 
		break; 
	}
    switch (stopBits)
	{
	case BSerialPort::StopOne:
		newtio.c_cflag &=  ~CSTOPB;
		break;
	case BSerialPort::StopOneAndHalf:
		break;
	case BSerialPort::StopTwo:
		newtio.c_cflag |=  CSTOPB;
		break;
	default:
		newtio.c_cflag = 0;
		break;
	}
      
	newtio.c_cc[VTIME]  = 0; 
	newtio.c_cc[VMIN] = 0; 
	tcflush(hcom, TCIFLUSH); 
	if((tcsetattr(hcom, TCSANOW, &newtio)) != 0) 
	{ 
		perror("com set error"); 
	} 
#endif

#ifdef _WIN32
	if (hcom == INVALID_HANDLE_VALUE)
		return;
	DCB dcb;
	GetCommState(hcom, &dcb);
	dcb.BaudRate = baudRate;
	dcb.fBinary = true;
	dcb.ByteSize = dataBits;
	switch (parity)
	{
	case BSerialPort::ParityOdd:
		dcb.Parity = ODDPARITY;
		break;
	case BSerialPort::ParityEven:
		dcb.Parity = EVENPARITY;
		break;
	case BSerialPort::ParityMark:
		dcb.Parity = MARKPARITY;
		break;
	case BSerialPort::ParitySpace:
		dcb.Parity = SPACEPARITY;
		break;
	default:
		dcb.Parity = 0;
		break;
	}
	switch (stopBits)
	{
	case BSerialPort::StopOne:
		dcb.StopBits = ONESTOPBIT;
		break;
	case BSerialPort::StopOneAndHalf:
		dcb.StopBits = ONE5STOPBITS;
		break;
	case BSerialPort::StopTwo:
		dcb.StopBits = TWOSTOPBITS;
		break;
	default:
		dcb.StopBits = ONESTOPBIT;
		break;
	}
	SetCommState(hcom, &dcb);
#endif
}

void member_BSerialPort::checkError()
{
	const char* errorStr = 0;
#ifdef _WIN32
	DWORD error = GetLastError();
	switch (error)
	{
	case ERROR_FILE_NOT_FOUND:
		errorStr = "SerialPort cannot be found.";
		break;

	case ERROR_INVALID_PARAMETER:
		errorStr = "SerialPort parameter is invalid.";
		break;
	}
#endif
	printf("%s : %s\n", portName.cstr(), errorStr);
}